﻿//-----------------------------------------------------------------------
// <copyright file="RepositoryFactory.cs" company="FastNET Services">
//     Copyright (c) 2008-2009. All Rights Reserved.
// </copyright>
// <license>
//     GPLv2
// </license>
// <warranty>
//     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
//     BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
//     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
//     DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
//     OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
// </warranty>
//-----------------------------------------------------------------------
#region Usings

using System;
using System.Configuration;
using System.Reflection;
using FastNET.CleanAct.Common.Repository.Configuration;
using FastNET.CleanAct.Common.Repository.Interfaces.Factories;
using FastNET.CleanAct.Common.Repository.Interfaces.Repositories.Base;

#endregion

namespace FastNET.CleanAct.Common.Repository
{
    /// <summary>
    /// Standard class for a configurable Repository Factory based on the .NET Provider Model
    /// </summary>
    public class RepositoryFactory : IRepositoryFactory
    {
        #region Variables

        private static RepositoryProviderBase currentProvider;

        #endregion

        #region CTor/DTor

        /// <summary>
        /// Initializes static members of the RepositoryFactory class
        /// </summary>
        static RepositoryFactory()
        {
            Initialize();
        }

        #endregion

        #region IRepositoryFactory Members

        /// <summary>
        /// Retrieves a repository for data related actions
        /// </summary>
        /// <typeparam name="T">A <typeparamref name="T"/> based reference to the type of repository needed</typeparam>
        /// <returns>A <typeparamref name="T"/> repository available to use</returns>
        public T GetRepository<T>() where T : class, IRepository
        {
            return currentProvider != null ? currentProvider.GetRepository<T>() : default(T);
        }

        #endregion

        #region Initialization

        /// <summary>
        /// Initializes the current provider statically into memory
        /// </summary>
        private static void Initialize()
        {
            RepositoryProviderConfiguration configuration = (RepositoryProviderConfiguration)ConfigurationManager.GetSection("RepositoryProvider");

            if (configuration == null)
            {
                throw new ConfigurationErrorsException("RepositoryProvider configuration section is not set correctly.");
            }

            Type provider = Type.GetType(configuration.Providers[configuration.Current].Type);

            if (!provider.IsSubclassOf(typeof(RepositoryProviderBase)))
            {
                throw new ConfigurationErrorsException("RepositoryProvider configuration section is not set correctly. Current Provider is not a vaild provider");
            }

            currentProvider = (RepositoryProviderBase)Activator.CreateInstance(provider);

            if (currentProvider == null)
            {
                throw new NullReferenceException("Current Provider could not be created");
            }

            currentProvider.Initialize(configuration.Providers[configuration.Current].Name, configuration.Providers[configuration.Current].Parameters);
        }

        #endregion
    }
}